package com.xishu.service;

import com.xishu.bo.ClosePayType;
import com.xishu.bo.CloseReport;
import com.xishu.bo.CustomerClosePayType;
import com.xishu.config.Config;
import com.xishu.entity.Company;
import com.xishu.entity.area.Area;
import com.xishu.entity.order.Order;
import com.xishu.entity.shop.PayType;
import com.xishu.entity.shop.Shop;
import com.xishu.util.DateUtil;
import com.xishu.util.Tools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class CloseReportService implements Tools {
    private static Logger logger = LoggerFactory.getLogger(CloseReportService.class);
    private static CloseReportService instance = new CloseReportService();
    private PayTypeService payTypeService = PayTypeService.getInstance();
    private ShopService shopService = ShopService.getInstance();
    private Config config = Config.getInstance();

    private CloseReportService() {
    }

    public static CloseReportService getInstance() {
        return instance;
    }

    /**
     * 详细报告里面的金额的计算
     *
     * @param order
     * @return
     */
    public Double getDetailCash(Order order) {
        if (config.isUsVersion()) {
            return showMoneyDouble(showDouble(order.getUserCost()) - getDouble(order.getTipsFee()) - getDouble(order.getServiceFee()));
        } else {
            return showMoneyDouble(order.getUserCost());
        }
    }

    /**
     * 添加净营收的HTML
     *
     * @param sb
     * @param shopInDb
     */
    public void addNetSales(StringBuilder sb, Shop shopInDb, boolean zh) {
        sb.append(String.format(" <tr>\n" +
                "            <td   colspan=\"3\" style=\"border: none;padding-top: 0.5rem;font-weight: bold;font-size: 1.5rem;padding-bottom: 0.5rem;\">%s</td>\n" +
                "            <td style=\"border: none;text-align: center;font-weight: bold;padding-bottom: 0.5rem;\">%s</td>\n" +
                "          </tr>", config.close_report_net_sale(zh), ReportService.getInstance().sumNetSale(shopInDb).toString()));

        //添加不含税的说明
        sb.append(String.format(" <tr>\n" +
                "            <td colspan=\"4\" style=\"border: none;border-bottom: 1px dashed;\">%s</td>\n" +
                "          </tr>", config.close_report_without_tax(zh)));
    }


    public void addSaleWithTax(StringBuilder sb, CloseReport closeReport, boolean zh) {
        //再添加营收，含税
        String net_sale_with_tax = config.close_report_net_sale_with_tax(zh);
        sb.append(String.format(" <tr>\n" +
                "            <td   colspan=\"3\" style=\"border: none;padding-top: 0.5rem;font-weight: bold;font-size: 1.5rem;padding-bottom: 0.5rem;\">%s</td>\n" +
                "            <td style=\"border: none;text-align: center;font-weight: bold;padding-bottom: 0.5rem;\">%s</td>\n" +
                "          </tr>", net_sale_with_tax, closeReport.getNetSaleWithTax()));

        String close_report_with_tax = config.close_report_with_tax(zh);
        sb.append(String.format(" <tr>\n" +
                "            <td colspan=\"4\" style=\"border: none;\">%s</td>\n" +
                "          </tr>", close_report_with_tax));
    }

    /**
     * 产生闭店报告数据
     *
     * @param shopId
     * @return
     */
    public CloseReport generateCloseReport(Long shopId) throws Exception {
        CloseReport closeReport = new CloseReport();

        //设置分店的名称
        Shop shop = shopService.findShopById(shopId);
        closeReport.setShopName_zh(shop.getName_zh());
        closeReport.setShopName_en(shop.getName_en());

        //设置餐厅的名称
        Company company = CompanyService.getInstance().findCompanyById(shop.getCompanyId());
        closeReport.setCompanyName(company.getName());

        //设置地址
        List<String> addressList_zh = new ArrayList<>();
        List<String> addressList_en = new ArrayList<>();
        if (config.isHkVersion()) {
            String shopAddress = shopService.getShopAddress(shop);
            if (isNotEmpty(shopAddress)) {
                List<Long> areaIdList = Arrays.stream(shopAddress.split(",")).map(p -> Long.valueOf(p)).collect(Collectors.toList());
                List<Area> areaList = shopService.findAreaList(areaIdList);

                addressList_zh.addAll(areaList.stream().map(p -> p.getName_zh()).collect(Collectors.toList()));
                addressList_en.addAll(areaList.stream().map(p -> p.getName_en()).collect(Collectors.toList()));
            } else {
                logger.info("can not get the shop address");
            }

            //最后添加详细地址
            addressList_zh.add(shop.getShopDetailAddress_zh());
            addressList_en.add(shop.getShopDetailAddress_en());
        } else {
            //美国版本
            //详细地址
            addressList_zh.add(shop.getUsAddress());
            addressList_en.add(shop.getUsAddress());

            //城市
            addressList_zh.add(shop.getUsCity());
            addressList_en.add(shop.getUsCity());

            //州
            if (isNotEmpty(shop.getUsState())) {
                addressList_zh.add(shopService.getStateAbbreviation(shop.getUsState()));
                addressList_en.add(shopService.getStateAbbreviation(shop.getUsState()));
            }

            //邮编
            addressList_zh.add(shop.getUsZip());
            addressList_en.add(shop.getUsZip());
        }

        closeReport.setAddressList_zh(addressList_zh);
        closeReport.setAddressList_en(addressList_en);

        //电话
        closeReport.setPhone(shop.getPhone());

        //日期
        if (getBoolean(shop.getBusinessStatus())){
            closeReport.setDate(DateUtil.formatDateMin(shop.getOpenTime()) + " - " + DateUtil.formatDateMin(System.currentTimeMillis()));
        }else {
            closeReport.setDate(DateUtil.formatDateMin(shop.getOpenTime()) + " - " + DateUtil.formatDateMin(shop.getCloseTime()));
        }


        /***支付方式统计 **/
        List<PayType> payTypeList = payTypeService.findPayTypeListCache_Stripe(shopId);

        List<ClosePayType> closePayTypes = payTypeList.stream().map(payType -> {
            Integer type = payType.getType();
            try {
                ClosePayType closePayType = new ClosePayType();
                PayType payTypeEntity = payTypeService.filterPayType(payTypeList, type);

                closePayType.setName_zh(payTypeEntity.getName_zh());
                closePayType.setName_en(payTypeEntity.getName_en());

                Double tangShiCash = ReportService.getInstance().sumTangShiCash(shopId, type);
                closePayType.setTangshi(tangShiCash);

                Double takeOutCash = ReportService.getInstance().sumTakeOutCash(shopId, type);
                closePayType.setTakeout(takeOutCash);

                closePayType.setTotal(getDouble(tangShiCash) + getDouble(takeOutCash));

                return closePayType;
            } catch (Exception e) {
                logger.error("e", e);
                return null;
            }
        }).filter(p -> p != null).collect(Collectors.toList());

        closeReport.setPayTypeList(closePayTypes);

        //添加销售额
        ClosePayType totalPayType = new ClosePayType();
        totalPayType.setTangshi(closePayTypes.stream().mapToDouble(p -> getDouble(p.getTangshi())).sum());
        totalPayType.setTakeout(closePayTypes.stream().mapToDouble(p -> getDouble(p.getTakeout())).sum());
        totalPayType.setTotal(closePayTypes.stream().mapToDouble(p -> getDouble(p.getTotal())).sum());
        closeReport.setTotalPayType(totalPayType);

        //添加服务费
        Double serviceFee = showMoneyDouble(ReportService.getInstance().sumServiceFee(shopId));
        closeReport.setServiceFee(serviceFee);

        //添加小费
        Double tips = showMoneyDouble(ReportService.getInstance().sumTipsFee(shopId));
        closeReport.setTipsFee(tips);

        //添加消费税
        Double consumptionFee = showMoneyDouble(ReportService.getInstance().sumConsumptionTax(shop.getId()));
        closeReport.setConsumptionFee(consumptionFee);

        //餐盒费
        Double packageFee = showMoneyDouble(ReportService.getInstance().sumPackageFee(shopId));
        closeReport.setPackageFee(packageFee);

        //外卖折扣
        Double takeOutDiscountFee = showMoneyDouble(ReportService.getInstance().sumTakeOutDiscount(shopId));
        closeReport.setTakeoutDiscountFee(takeOutDiscountFee);

        //优惠券
        Double discountFee = showMoneyDouble(ReportService.getInstance().sumDiscountFee(shopId));
        closeReport.setDiscountFee(discountFee);

        //未支付
        ClosePayType unPaidPayType = new ClosePayType();
        double tangShiUnpaid = showMoneyDouble(ReportService.getInstance().countSendToKitchenUnpaidForTangShi(shopId));
        unPaidPayType.setTangshi(tangShiUnpaid);
        double takeOutUnpaid = showMoneyDouble(ReportService.getInstance().sumSendToKitchenUnpaidForTakeOut(shopId));
        unPaidPayType.setTakeout(takeOutUnpaid);
        unPaidPayType.setTotal(tangShiUnpaid + takeOutUnpaid);
        closeReport.setUnPayed(unPaidPayType);

        //已退款
        ClosePayType returnCashPayType = new ClosePayType();
        double tangShiReturnCash = showMoneyDouble(ReportService.getInstance().returnCashForTangShi(shopId));
        returnCashPayType.setTangshi(tangShiReturnCash);
        double takeOutReturnCash = showMoneyDouble(ReportService.getInstance().returnCashForTakeOut(shopId));
        returnCashPayType.setTakeout(takeOutReturnCash);
        returnCashPayType.setTotal(tangShiReturnCash + takeOutReturnCash);
        closeReport.setReturnCash(returnCashPayType);

        //客流量
        int dinners = getInt(ReportService.getInstance().dinners(shopId));
        closeReport.setDinners(dinners);

        //订单量
        int orderNumber = getInt(ReportService.getInstance().orderNumber(shopId));
        closeReport.setOrderNumber(orderNumber);

        //删除订单量
        int deleteOrderNumber = ReportService.getInstance().deleteOrderNumber(shopId);
        closeReport.setDeleteOrderNumber(deleteOrderNumber);

        //删除菜品
        int deleteOrderItemNumber = ReportService.getInstance().deleteOrderItemNumber(shopId);
        closeReport.setDeleteOrderItemNumber(deleteOrderItemNumber);

        //餐厅堂食
        int tangShiOrderNumber = getInt(ReportService.getInstance().tangShiOrderNumber(shopId));
        closeReport.setTangshiOrderNumber(tangShiOrderNumber);

        //餐厅外卖
        int takeOutOrderNumber = getInt(ReportService.getInstance().takeOutOrderNumber(shopId));
        closeReport.setTakeoutOrderNumber(takeOutOrderNumber);

        //外卖平台
        int takeOutPlatNumber = ReportService.getInstance().countPlatOrderNumber(shopId);
        closeReport.setTakeoutPlatNumber(takeOutPlatNumber);


        //是否显示会员报告
        closeReport.setCustomerReportOpen(company.getCompanyConfig().getCustomerOpen());

        /**会员报告**/
        //需要的时候，才去获取数据
        if (closeReport.getCustomerReportOpen()) {
            ArrayList<CustomerClosePayType> customerClosePayTypeList = new ArrayList<>();

            List<PayType> customerPayTypeList = payTypeService.findPayTypeListCache_Stripe(shopId);

            for (PayType payTypeEntity : customerPayTypeList) {
                CustomerClosePayType customerClosePayType = new CustomerClosePayType();
                Integer payType = payTypeEntity.getType();
                customerClosePayType.setName_zh(payTypeEntity.getName_zh());
                customerClosePayType.setName_en(payTypeEntity.getName_en());
                double sumVip = ReportService.getInstance().sumVip(shop, payType);
                customerClosePayType.setVipFee(sumVip);
                double otherFee = ReportService.getInstance().sumCash(shopId, payType);
                customerClosePayType.setVipFeeAndOther(sumVip + otherFee);
                customerClosePayTypeList.add(customerClosePayType);
            }

            closeReport.setCustomerPayTypeList(customerClosePayTypeList);

            CustomerClosePayType customerTotalPayType = new CustomerClosePayType();
            customerTotalPayType.setVipFee(customerClosePayTypeList.stream().mapToDouble(p -> p.getVipFee()).sum());
            customerTotalPayType.setVipFeeAndOther(customerClosePayTypeList.stream().mapToDouble(p -> p.getVipFeeAndOther()).sum());

            closeReport.setCustomerTotalPayType(customerTotalPayType);
        }

        //美国版本添加净营收
        if (config.isUsVersion()) {
            Double netSale = ReportService.getInstance().sumNetSale(shop);
            closeReport.setNetSale(netSale);

            double netSaleWithTax = ReportService.getInstance().sumNetSaleWithTax(shop);
            closeReport.setNetSaleWithTax(netSaleWithTax);
        }

        return closeReport;
    }

}
